module(..., package.seeall) -- 使得文件中的函数在何处都可调用
require "pins" -- 用到了pin库，该库为luatask专用库，需要进行引用
require "sys"
require "uartTask"
require "audio"
require "math"
require "nvm"
require "send433RFSignal"
require "logGenerator"
nvm.init("config.lua", true)
local ttsStr = "预警系统演练"
local toneDowns, toneBreak, doToneTask, lampDowns, lampBreak, doLampTask,
      signalDowns, signalBreak, doSignalTask, countDownSDrill, quake_intensity,
      equipment_clients, alarm433Bool, warnCancelTTSBroadcastCount = 0, false,
                                                                     true, 0,
                                                                     false,
                                                                     true, 0,
                                                                     false,
                                                                     true, 0, 0,
                                                                     "", false,
                                                                     0
TTS = 1
local setGpio9Fnc = pins.setup(pio.P0_9, 1) -- 静音设置（高电平静音）
local setGpio13Fnc = pins.setup(pio.P0_13, 0) -- 预警指示
local setGpio10Fnc = pins.setup(pio.P0_10, 0) -- Buzzer正常低电平，预警高电平
local setGpio17Fnc = pins.setup(pio.P0_17, 0) -- 地震预警测试音量控制，高电平为测试音量（音量小），低电平为正常音量（音量大）
-- local setGpio12Fnc = pins.setup(pio.P0_12, 0) -- 报警灯
-- 获取配置参数
local configIntensity, enableRF433, countDown, alertSound, alertLight,
      magnitudeConfig, centerIntensityConfig, emergencyLamp, relay, luminance,
      alertVolume, blueLimit, yellowLimit, orangeLimit, redLimit, afterSecond,
      exerciseText, cancelCount = tonumber(nvm.get("intensity")),
                                  nvm.get("enableRF433"),
                                  tonumber(nvm.get("countDown")),
                                  tonumber(nvm.get("alertSound")),
                                  tonumber(nvm.get("alertLight")),
                                  tonumber(nvm.get("magnitude")),
                                  tonumber(nvm.get("centerIntensity")),
                                  tonumber(nvm.get("emergencyLamp")),
                                  tonumber(nvm.get("relay")),
                                  tonumber(nvm.get("luminance")),
                                  tonumber(nvm.get("alertVolume")),
                                  tonumber(nvm.get("blueLimit")),
                                  tonumber(nvm.get("yellowLimit")),
                                  tonumber(nvm.get("orangeLimit")),
                                  tonumber(nvm.get("redLimit")),
                                  tonumber(nvm.get("afterSecond")),
                                  nvm.get("exerciseText"),
                                  tonumber(nvm.get("cancelCount"))

-- 报警灯操作任务
local function alarmLampOperationTask()
    -- local count = 0
    doLampTask = false
    lampDowns = 0
    setGpio10Fnc(1)
    log.info("alarmLamp enter Dril")
    while lampDowns >= 0 and lampDowns <= 5400 do
        --[[ while count ~= 4 do
            setGpio12Fnc(1)
            sys.wait(125)
            setGpio12Fnc(0)
            sys.wait(125)
            count = count + 1
            if toneBreak then
                break
            end
        end ]]
        if lampBreak then
            lampDowns = 0
            lampBreak = false
            break
        end
        -- count = 0
        -- lampDowns = lampDowns - 1
        sys.wait(1000)
        if lampBreak then
            lampDowns = 0
            lampBreak = false
            break
        end
        lampDowns = lampDowns + 1
    end
    -- setGpio12Fnc(0)
    setGpio10Fnc(0)
    doLampTask = true
end

-- 发送433信号
local function send433SignalTask(countSignalDownS)
    local afterSecondCount = afterSecond
    doSignalTask = false
    setGpio9Fnc(0)
    signalDowns = countSignalDownS
    send433RFSignal.InterruptSendMsg = true
    send433RFSignal.sendMsgTask()
    if not send433RFSignal.TimeId then
        send433RFSignal.signalRF433SerialCommunication(signalDowns,
                                                       quake_intensity, "1",
                                                       alarm433Bool)
    end
    sys.wait(1000)
    signalDowns = signalDowns - 1
    while signalDowns > 0 do
        if signalDowns == 1 and afterSecondCount == 0 then
            alarm433Bool = true
        end
        if not send433RFSignal.TimeId then
            send433RFSignal.signalRF433SerialCommunication(signalDowns,
                                                           quake_intensity, "1",
                                                           alarm433Bool)
        end
        if signalBreak then
            signalBreak = false
            signalDowns = 0
            break
        end
        sys.wait(1000)
        if signalBreak then
            signalBreak = false
            signalDowns = 0
            break
        end
        signalDowns = signalDowns - 1
    end
    while afterSecondCount > 0 do
        log.info("afterSecondCount:", afterSecondCount)
        if afterSecondCount == 1 then alarm433Bool = true end
        if signalBreak then
            signalBreak = false
            signalDowns = 0
            break
        end
        if not send433RFSignal.TimeId then
            send433RFSignal.signalRF433SerialCommunication(1, quake_intensity,
                                                           "0", alarm433Bool)
        end
        sys.wait(1000)
        if signalBreak then
            signalBreak = false
            signalDowns = 0
            break
        end
        afterSecondCount = afterSecondCount - 1
    end
    setGpio9Fnc(1) -- 报警结束设置静音
    doSignalTask = true
    alarm433Bool = false
    sys.wait(5000)
    setGpio17Fnc(0) -- 音量测试恢复正常（大音量）
end

-- 声音报警
local function alarmVoiceTask(countToneDownS)
    local waitCout = afterSecond
    doToneTask = false
    setGpio9Fnc(0)
    setGpio13Fnc(1)
    toneDowns = countToneDownS
    if string.len(exerciseText) > 0 then
        ttsStr = exerciseText
    else
        ttsStr = "地震预警演练，地震预警演练"
    end
    audio.play(TTS, "TTS", ttsStr, 7)
    while toneDowns > 0 do
        log.info("setGpio1Fnc")
        if toneDowns <= 10 then
            log.info("tts voice")
            ttsStr = tostring(toneDowns)
            audio.play(TTS, "TTS", ttsStr, 7)
        end
        -- if math.fmod(countAlarmDrill, 12) == 0 then uartTask.write(0x0C) end
        if toneBreak then
            -- uartTask.write(0x0C)
            toneBreak = false
            toneDowns = 0
            break
        end
        sys.wait(1000)
        if toneBreak then
            -- uartTask.write(0x0C)
            toneBreak = false
            toneDowns = 0
            break
        end
        toneDowns = toneDowns - 1
        -- countAlarmDrill = countAlarmDrill + 1
    end
    log.info("waitCout0", waitCout)
    while waitCout > 0 do
        log.info("waitCout1", waitCout)
        sys.wait(1000)
        waitCout = waitCout - 1
    end
    setGpio9Fnc(1) -- 报警结束设置静音
    setGpio17Fnc(0) -- 音量测试恢复正常（大音量）
    setGpio13Fnc(0)
    doToneTask = true
end

-- 烈度转换为阈值
local function intensity2Threshold(intensity2Th)
    local threhold = 0
    if intensity2Th >= blueLimit and intensity2Th < yellowLimit then
        threhold = 1
    elseif intensity2Th >= yellowLimit and intensity2Th < orangeLimit then
        threhold = 2
    elseif intensity2Th >= orangeLimit and intensity2Th < redLimit then
        threhold = 3
    elseif intensity2Th >= redLimit then
        threhold = 4
    end
    return threhold
end

-- 地震预警系统
-- 两个功能：1.预警系统演练（tts语音播报3遍同时报警音触发）
-- 入参：mqttData接收的预警信息
function EarthquakeWarningDrillSystem(tjsondata)
    local msgCode, tClock, sysTime, eqlogInfo, errInfo = nil, os.date("*t"), "",
                                                         "", ""
    sysTime = string.format("%04d-%02d-%02d %02d:%02d:%02d", tClock.year,
                            tClock.month, tClock.day, tClock.hour, tClock.min,
                            tClock.sec)
    if "false" == enableRF433 then
        enableRF433 = false
    elseif "true" == enableRF433 then
        enableRF433 = true
    end
    if alertVolume <= 50 then setGpio17Fnc(1) end
    if not tjsondata["1"] then
        countDownSDrill = 0
    else
        countDownSDrill = tonumber(tjsondata["1"])
    end
    if not tjsondata["2"] then
        quake_intensity = 0
    else
        quake_intensity = tonumber(tjsondata["2"])
    end
    if tjsondata["16"] then msgCode = tjsondata["16"] end
    log.info("tacountDownSDrillg", countDownSDrill, "quake_intensity",
             quake_intensity, "msgCode", msgCode)
    if msgCode == "0199" or quake_intensity == 0 then
        eqlogInfo = eqlogInfo .. "[" .. sysTime .. "]" ..
                        "预警演习取消！级\n"
        audio.stop()
        audio.play(TTS, "TTS",
                   "预警系统演练取消。预警系统演练取消。预警系统演练取消",
                   7)
        sys.wait(6400)
        if toneDowns > 0 then toneBreak = true end
        if lampDowns > 0 and lampDowns < 5400 then lampBreak = true end
        if signalDowns > 0 then signalBreak = true end
        while not doSignalTask do sys.wait(800) end
        if not send433RFSignal.TimeId then
            send433RFSignal.InterruptSendMsg = false
            send433RFSignal.sendMsgTask()
        end

    else
        eqlogInfo = eqlogInfo .. "[" .. sysTime .. "]" ..
                        "[预警演习:]到达秒数:" .. countDownSDrill ..
                        "s,地震烈度:" .. quake_intensity .. "级\n"
        if toneDowns > 0 then toneBreak = true end
        if lampDowns > 0 and lampDowns < 5400 then lampBreak = true end
        if signalDowns > 0 then signalBreak = true end
        while not doLampTask do sys.wait(800) end
        -- 报警灯任务
        log.info("alertLight", alertLight)
        if intensity2Threshold(quake_intensity) >= alertLight and doLampTask then
            log.info("enter alertLight")
            sys.taskInit(alarmLampOperationTask)
        else
            eqlogInfo = eqlogInfo .. "[" .. sysTime .. "]" ..
                            "[不满足报警灯临界值：]" ..
                            "烈度转阈值：" ..
                            tostring(intensity2Threshold(quake_intensity)) ..
                            ",报警灯预设值：" .. alertLight ..
                            "[执行报警灯任务:]" .. tostring(doLampTask) ..
                            "\n"
        end
        while not doSignalTask do sys.wait(800) end
        -- 433信号发送任务
        if intensity2Threshold(quake_intensity) >= alertSound and enableRF433 and
            doSignalTask then
            log.info("433send")
            sys.wait(200)
            sys.taskInit(send433SignalTask, countDownSDrill)
        else
            eqlogInfo = eqlogInfo .. "[" .. sysTime .. "]" ..
                            "[阈值，发送433，执行发送433信号存在条件不满足]" ..
                            "烈度转阈值：" ..
                            tostring(intensity2Threshold(quake_intensity)) ..
                            ",设定阈值：" .. alertSound ..
                            "是否发送433:" .. tostring(enableRF433) ..
                            "执行发送433信号任务" ..
                            tostring(doSignalTask) .. "\n"
        end
        log.info("alertSound", alertSound)
        while not doToneTask do sys.wait(800) end
        -- 报警音任务
        log.info("alertSound", alertSound)
        if intensity2Threshold(quake_intensity) >= countDown and doToneTask and
            quake_intensity >= configIntensity then
            log.info("alertSound enter")
            sys.wait(200)
            sys.taskInit(alarmVoiceTask, countDownSDrill)
            --[[ if doToneTask and quake_intensity >= configIntensity then
            log.info("alertSound enter")
            sys.wait(200)
            sys.taskInit(alarmVoiceTask, countDownSDrill) ]]
        else
            eqlogInfo = eqlogInfo .. "[" .. sysTime .. "]" ..
                            "[不满足报警音临界值：]" ..
                            "烈度阈值：" ..
                            tostring(intensity2Threshold(quake_intensity)) ..
                            ",报警音预设值：" .. countDown ..
                            ",[执行报警音任务:]" .. tostring(doToneTask) ..
                            "\n"

        end
    end
    if eqlogInfo ~= "" and eqlogInfo ~= false then
        log.info("生成eq日志")
        logGenerator.generateLogTask(eqlogInfo, "eqlog")
    end
    if errInfo ~= "" and errInfo ~= false then
        log.info("生成错误日志", errInfo)
        logGenerator.generateLogTask(errInfo, "error")
    end
end
